package sicnu.cs.aps.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import sicnu.cs.aps.common.enums.ActivitySignEnum;
import sicnu.cs.aps.common.util.CopyUtil;
import sicnu.cs.aps.common.util.RequestUtil;
import sicnu.cs.aps.domain.dto.*;
import sicnu.cs.aps.domain.entity.Activity;
import sicnu.cs.aps.domain.entity.ActivityPlan;
import sicnu.cs.aps.domain.entity.ActivityTeam;
import sicnu.cs.aps.domain.form.ActivityTeamQueryForm;
import sicnu.cs.aps.domain.vo.*;
import sicnu.cs.aps.mapper.ActivityTeamMapper;
import sicnu.cs.aps.service.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * description 队伍信息service
 *
 * @author chenhetao
 * @version 1.0
 * @className ActivityTeamServiceImpl
 * @packageName sicnu.cs.aps.service.impl
 * @date 2022/5/31 09:47
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ActivityTeamServiceImpl implements IActivityTeamService {

    private final ActivityTeamMapper teamMapper;
    private final IActivityAuditService auditService;
    private final IActivityService activityService;
    private final IActivityPlanService planService;
    private final IActivityTeamFeedbackService feedbackService;
    private final IActivityFormService formService;

    @Override
    public ActivityTeam getTeamById(Long teamId) {
        return teamMapper.selectByTeamId(teamId);
    }

    /**
     * 通过队伍id查询队伍的详细信息
     *
     * @return 队伍的详细信息
     */
    @Override
    public TeamInfoVo getTeamDetailById(Long teamId) {


        //学院只能查询本学院的小队信息
        //学校可以查看任意小队的小队信息

        if (RequestUtil.isCurrentUserTeacherOrStu()) {
            log.info("用户为老师或学生");
            //学生和老师只能查询本人的小队信息
//            teamQueryDto.setCurrentId(RequestUtil.getCurrentUserId());
        } else if (RequestUtil.isCurrentUserACollege()) {
            log.info("用户为学院");
            //TODO 完善权限设计
//            if (teamQueryDto.getCollegeId() != null) {
//                //非法传参处理
//                log.warn("学院不允许筛选学院");
//                return null;
//            }
            //学院只能查询本学院的小队信息
//            teamQueryDto.setCollegeId(RequestUtil.getCurrentUserId());
        } else {
            //学校可以查看任意小队的小队信息
            log.info("用户为学校");
        }

        //装载基础信息
        TeamInfoVo teamInfoVo = new TeamInfoVo();
        ActivityTeam teamById = getTeamById(teamId);
        if (teamById == null) {
            log.error("队伍未找到");
            return null;
        }
        BeanUtils.copyProperties(teamById, teamInfoVo, TeamInfoVo.class);


        //装载活动信息
        teamInfoVo.setActivityName(activityService.getById(teamInfoVo.getActivityId()).getTitle());

        //装载队长信息
        teamInfoVo.setCaptain(CopyUtil.copy(teamMapper.selectCaptionInTeam(teamId), StudentInfoVo.class));

        //装载学生信息
        teamInfoVo.setStudents(CopyUtil.copyList(teamMapper.listStudentInTeam(teamId), StudentInfoVo.class));

        //装载老师信息
        teamInfoVo.setTeacher(CopyUtil.copy(teamMapper.selectTeacherInTeam(teamId), TeacherInfoVo.class));

        //装载时间线信息
        List<TimeEventVo> timeEventVos = loadTimeEvent(teamId);
        teamInfoVo.setTimeEvents(timeEventVos);

        //装载小队策划信息
        ActivityPlan planByTeamId = planService.getPlanByTeamId(teamId);

        if (planByTeamId != null) {
            teamInfoVo.setPlan(CopyUtil.copy(planByTeamId, ActivityPlanVo.class));
        }

        //装载学院审核的意见信息
        timeEventVos.stream()
                .filter(timeEventVo -> ActivitySignEnum.isCollegeEvent(timeEventVo.getOpEvent()))
                .max(Comparator.comparing(TimeEventVo::getOpTime))
                .ifPresentOrElse(vo -> teamInfoVo.setCollegeOpinion(vo.getOpEventDesc()), () -> {
                    log.warn("无学院审核意见");
                });

        //装载学校审核的意见信息
        timeEventVos.stream()
                .filter(timeEventVo -> ActivitySignEnum.isUniversityEvent(timeEventVo.getOpEvent()))
                .max(Comparator.comparing(TimeEventVo::getOpTime))
                .ifPresentOrElse(vo -> teamInfoVo.setUniversityOpinion(vo.getOpEventDesc()), () -> log.warn("无学校审核意见"));

        //装载最后操作时间
        timeEventVos.stream()
                .filter(s -> s.getOpTime().getTime() < System.currentTimeMillis())
                .max(Comparator.comparing(TimeEventVo::getOpTime))
                .ifPresentOrElse(vo -> teamInfoVo.setLastOpTime(vo.getOpTime()), () -> log.warn("操作时间获取异常"));

        return teamInfoVo;
    }

    /**
     * 获取小队创建时间线信息
     *
     * @param teamId 小队id
     * @return 创建时间线信息
     */
    @Override
    public TimeEventVo getTeamCreateTimeLine(Long teamId) {
        ActivityTeam activityTeam = teamMapper.selectByTeamId(teamId);
        if (activityTeam == null) {
            return null;
        }
        return TimeEventVo.builder()
                .opTime(activityTeam.getCreateTime())
                .opDesc("队伍创建")
                .operatorId(activityTeam.getUserId())
                //TODO 处理队长姓名问题
                .operatorName("队长")
                .opEvent(ActivitySignEnum.SIGN_PASS_NO_PLAN)
                .build();
    }

    /**
     * 通过查询form查询小队列表
     *
     * @param teamQueryForm 条件及分页信息
     * @return 小队列表
     */
    @Override
    public PageInfo<TeamInfoVo> listTeamDetailByForm(ActivityTeamQueryForm teamQueryForm) {

        ActivityTeamQueryDto teamQueryDto = new ActivityTeamQueryDto();
        BeanUtils.copyProperties(teamQueryForm, teamQueryDto);
        if (RequestUtil.isCurrentUserTeacherOrStu()) {
            log.info("用户为老师或学生");
            //学生和老师只能查询本人的小队信息
            teamQueryDto.setCurrentId(RequestUtil.getCurrentUserId());
        } else if (RequestUtil.isCurrentUserACollege()) {
            log.info("用户为学院");
            if (teamQueryDto.getCollegeId() != null) {
                //非法传参处理
                log.warn("学院不允许筛选学院");
                return null;
            }
            //学院只能查询本学院的小队信息
            teamQueryDto.setCollegeId(RequestUtil.getCurrentUserId());
        } else {
            //学校可以查看任意小队的小队信息
            log.info("用户为学校");
        }

        //映射需要查询的类型
        teamQueryDto.setState(ActivitySignEnum.analyzeCode(teamQueryForm.getState()));

        PageHelper.startPage(teamQueryForm.getPageNum(), teamQueryForm.getPageSize());
        List<TeamInfoVo> activityTeams = CopyUtil.copyList(teamMapper.listTeamByCondition(teamQueryDto), TeamInfoVo.class);
//        teamMapper.listStudentInTeam(teamId)

        //获取小队id列表
        List<Long> teamIds = activityTeams.stream().map(TeamInfoVo::getId).collect(Collectors.toList());

        if (!teamIds.isEmpty()) {

            //查询范围内所有活动信息
            List<Activity> activities = activityService.listByTeamIds(teamIds);
            //查询范围内所有队长信息
            List<TeamStuDto> captionInfos = teamMapper.listCaptionInTeams(teamIds);
            //查询范围内所有学生信息
            List<TeamStuDto> studentInfos = teamMapper.listStudentInTeams(teamIds);
            //查询范围内所有老师信息
            List<TeamTeacherDto> teacherInfos = teamMapper.listTeacherInTeams(teamIds);
            //查询范围内所有策划信息
            List<TeamPlanDto> planInfos = planService.listPlanInTeams(teamIds);
            //查询范围内所有问卷信息
            List<AnswerKvDto> answerDtoList = formService.listQaInTeams(activityTeams,teamIds);



            activityTeams.forEach(activityTeam ->
                    {
                        Optional<String> activityOptional = activities.stream()
                                .filter(activity -> activity.getId().equals(activityTeam.getActivityId()))
                                .map(Activity::getTitle)
                                .findFirst();
                        activityTeam.setActivityName(activityOptional.orElse(null));
                        activityTeam.setStudents(
                                CopyUtil.copyList(
                                        studentInfos.stream()
                                                .filter(captionInfo -> captionInfo.getTeamId().equals(activityTeam.getId()))
                                                .collect(Collectors.toList())
                                        , StudentInfoVo.class)
                        );

                        Optional<TeamTeacherDto> teamTeacherOptional = teacherInfos.stream()
                                .filter(teamTeacherDto -> teamTeacherDto.getTeamId().equals(activityTeam.getId()))
                                .findFirst();
                        activityTeam.setTeacher(
                                teamTeacherOptional.map(teamTeacherDto ->
                                                CopyUtil.copy(teamTeacherDto, TeacherInfoVo.class))
                                        .orElse(null)
                        );

                        captionInfos.stream()
                                .filter(captionInfo -> captionInfo.getTeamId().equals(activityTeam.getId()))
                                .findFirst()
                                .ifPresentOrElse(at -> activityTeam.setCaptain(CopyUtil.copy(at, StudentInfoVo.class)), () -> log.error("队长获取发生异常"));
                        Optional<TeamPlanDto> teamPlanOptional = planInfos.stream()
                                .filter(planInfo -> planInfo.getTeamId().equals(activityTeam.getId()))
                                .findFirst();
                        activityTeam.setPlan(
                                teamPlanOptional.map(teamPlanDto ->
                                                CopyUtil.copy(teamPlanDto, ActivityPlanVo.class))
                                        .orElse(null)
                        );

//                        List<AnswerKvDto> collect = answerDtoList.stream()
//                                .filter(answerKv -> answerKv.getTeamId().equals(activityTeam.getId()))
//                                .collect(Collectors.toList());
//                        if (!collect.isEmpty()){
//                            activityTeam.setQuestionAnswer(CopyUtil.copyList(collect,AnswerKvVo.class));
//                        }

                        activityTeam.setQuestionAnswer(answerDtoList.stream().filter( a -> a.getTeamId().equals(activityTeam.getId())).findFirst().orElse(null));

                    }
            );
        }


        return new PageInfo<>(activityTeams);
    }

    /**
     * 更新队伍的状态 活动开始 （审核通过->进行中 进行中->待反馈）
     */
    @Override
    public void updateTeamState() {
        teamMapper.updateToActivityOnState();
        teamMapper.updateToFeedbackState();
    }

    /**
     * 装载时间线信息
     *
     * @param teamId 小队id
     * @return 时间线信息
     */
    private List<TimeEventVo> loadTimeEvent(Long teamId) {
        List<TimeEventVo> timeEventVos = new ArrayList<>();

        //插入小队创建时间
        TimeEventVo createTimeLine = this.getTeamCreateTimeLine(teamId);
        if (createTimeLine != null) {
            timeEventVos.add(createTimeLine);
        } else {
            log.warn("小队时间线创建失败");
        }

        //插入审核时间线
        List<TimeEventVo> auditTimeLine = auditService.listTeamAuditTimeLine(teamId);
        if (auditTimeLine != null) {
            timeEventVos.addAll(auditTimeLine);
        } else {
            log.warn("审核时间线创建失败");
        }

        //插入预计开始和预计结束时间
        List<TimeEventVo> planTimeLine = planService.listTeamPlanTimeLine(teamId);
        if (planTimeLine != null) {
            timeEventVos.addAll(planTimeLine);
        } else {
            log.warn("预计开始和预计结束时间线创建失败");
        }
        //插入活动实际完成时间
        TimeEventVo completeTimeLine = feedbackService.getTeamCompleteTimeLine(teamId);
        if (completeTimeLine != null) {
            timeEventVos.add(completeTimeLine);
        } else {
            log.warn("活动实际完成时间创建失败");
        }

        return timeEventVos;
    }
}
